//
// Created by Tony on 2024/5/20.
//

#ifndef PARSER_ABS_PARSER_H
#define PARSER_ABS_PARSER_H

#include "../common/ErrorRecorder.h"
#include "../lexer/TokenQueue.h"
#include "ast/Ast.h"
#include "ast/leaf/Name.h"
#include "ast/list/AccessFlags.h"
#include "ast/list/TypeTag.h"
#include "ast/list/array/ArrayIndex.h"
#include "ast/list/function/ArgumentList.h"
#include "ast/list/function/ParameterList.h"

namespace Parser {

/**
 * 本项目使用到的BNF规则如下：
 *
 * { pat }      模式pat至少重复0次
 * [ pat ]      模式pat出现0次或者1次
 * pat1 | pat2  与模式pat1或者pat2匹配
 * ()           将括号内视为一个完整的模式
 */

class AbsParser : public ErrorRecorder {
protected:
    Lexer::TokenQueue tokenQueue;

public:
    AbsParser() = default;

    void setTokenQueue(Lexer::TokenQueue queue) { tokenQueue = std::move(queue); }

    virtual shared_ptr<Ast> parse() = 0;

protected:
    static bool isPunct(const shared_ptr<Lexer::Token>& token, const char* punct);
    static bool isName(const shared_ptr<Lexer::Token>& token, const char* name);

    bool skipPunct(const char* punct);
    bool skipName(const string& name);

    shared_ptr<Name> name();
    shared_ptr<Ast> primary();
    shared_ptr<Ast> factor();
    shared_ptr<TypeTag> typeTag();
    shared_ptr<AccessFlags> accessFlags();
    shared_ptr<ParameterList> parameterList();
    shared_ptr<ArgumentList> argumentList();
    shared_ptr<ArrayIndex> arrayIndex();

    virtual shared_ptr<Ast> expr() = 0;

private:
    vector<shared_ptr<Ast>> postfix();
};

} // namespace Parser

#endif // PARSER_ABS_PARSER_H
